home *** CD-ROM | disk | FTP | other *** search
-
- **********************************************************************
- *
- * AnyLongToStr - Convert 32-bit value to ASCII
- *
- * Input: d0 - the value to convert
- * d1 - flags
- * a0 - pointer to a buffer
- * Output: d0 - number of characters written (or null for error)
- * a0 - address of the terminating null
- *
- *
- * Flags are:
- * LTS_DECIMAL - normal decimal conversion
- * LTS_SIGN_LONG - decimal signed mode (longword)
- * LTS_SIGN_WORD - signed (word)
- * LTS_SIGN_BYTE - signed (byte)
- * LTS_BINARY - convert to binary
- * LTS_HEX_UPPER - convert to hex (A-F)
- * LTS_HEX_LOWER - convert to hex (a-f)
- *
- *
- * You should pass a buffer with at least 11/12 (decimal/negative
- * decimal), 9 (hex) or 33 (binary) bytes of space.
- * If flags = #1, checks the 31 bit and if it is high, assumes
- * the value is lower than 0.
- * This string is null-terminated. Address of the terminating
- * null is returned in a0. The null is included in number of chars
- * written.
- *
- * When you specify decimal non-signed mode, then even if
- * bit 31 is set you'll get value in range 0 to 4.294.967.295. In
- * signed mode you'll get values in range from -2.147.483.647 to
- * 2.147.483.648 (negative when bit 31/15/7 is set, depending on the
- * choosen mode). Minus sign is written, if needed (and added to chars
- * counter returned in d0).
- *
- * No prefix is written in hex/bin mode!!! If you need it, write
- * it yourself. That's how you can choose between '$'/'0x' :-)
- *
- * Alters only scratch registers (d0, d1, a0, a1). Uses 12 bytes
- * of stack.
- *
- *
- * © 1996 by Tadek Knapik (tadek@student.uci.agh.edu.pl).
- * Public Domain. E-mail appreciated :-)
- *
- **********************************************************************
-
-
- LTS_DECIMAL equ 0
- LTS_BINARY equ 2
- LTS_HEX_UPPER equ 4
- LTS_HEX_LOWER equ 8
- LTS_SIGN_LONG equ 16
- LTS_SIGN_WORD equ 32
- LTS_SIGN_BYTE equ 64
- LTS_NEGATIVE equ LTS_SIGN_LONG
- LTS_HEX equ LTS_HEX_UPPER
-
-
- AnyLongToStr:
- movem.l d2-d4,-(sp)
- moveq #0,d2 ;the counter
-
- cmpi.l #LTS_DECIMAL,d1
- beq LTSDecConvert
-
- cmpi.l #LTS_SIGN_LONG,d1
- beq LTSMinDecConvert
-
- cmpi.l #LTS_SIGN_WORD,d1
- beq LTSMinWDecConvert
-
- cmpi.l #LTS_SIGN_BYTE,d1
- beq LTSMinBDecConvert
-
- cmpi.l #LTS_BINARY,d1
- beq LTSBinConvert
-
- move.l #'A',d2 ;ASCII base uppercased
-
- cmpi.l #LTS_HEX_UPPER,d1
- beq LTSHexConvert
-
- move.l #'a',d2 ;ASCII base lowercased
-
- cmpi.l #LTS_HEX_LOWER,d1
- beq LTSHexConvert
-
- LTSError:
- movem.l (sp)+,d2-d4
- moveq #0,d1
- moveq #0,d0
- rts
-
- ;--------------------
-
- LTSMinBDecConvert:
- ext.w d0 ;extend to word
- LTSMinWDecConvert
- ext.l d0 ;extend to longword
-
- LTSMinDecConvert:
- btst #31,d0
- beq LTSDecConvert
- move.b #'-',(a0)+ ;the minus sign
- addq.l #1,d2
- neg.l d0 ;so I need plus now
-
- LTSDecConvert:
- moveq #0,d1 ;zeroes flag
- move.l #1000000000,d4 ;32-bit max power of 10
-
- LTSDecAgain:
- cmp.l d4,d0
- bcc LTSDecMatch
-
- tst.l d1 ;write zeroes?
- beq LTSDecNextPass ;not yet
-
- move.b #'0',(a0)+ ;write it
- addq.l #1,d2 ;one character more
- bra LTSDecNextPass
-
- LTSDecMatch:
- moveq #1,d1 ;means write zeros from now
- moveq #0,d3 ;clear temporary
-
- LTSDecLoop:
- addq.l #1,d3 ;
-
- sub.l d4,d0
- bpl LTSDecLoop ;branch if not less than 0
-
- add.l d4,d0 ;did it too many times
- subq.l #1,d3 ;as well
-
- addi.l #'0',d3 ;ASCII 0
- move.b d3,(a0)+
- addq.l #1,d2 ;the counter
-
- LTSDecNextPass:
- bsr LTSDecDivideByTen
- tst.l d4
- beq LTSError
-
- cmpi.l #1,d4
- bne LTSDecAgain
-
- ;less than 10 in d0..
-
- addi.l #'0',d0
- move.b d0,(a0)+
- addq.l #1,d2
-
- LTSDecOver:
- move.b #0,(a0)
- suba.l #1,a0
- addq.l #1,d2 ;null is a character, too
- move.l d2,d0
- movem.l (sp)+,d2-d4
- rts
-
-
- LTSDecDivideByTen:
-
- ;
- ;if your proggy is to be run on 020+ only!
- ; But beware! It is one of instructions not present on 68060! And it
- ;will be significantly slower, because it is emulated in software then.
- ;
- ; divu.l #10,d4
- ; rts
-
- ;now 68000 part. Thanks for Simon N Goodwin for this routine!
-
- moveq #0,d3 ;temporary register
- swap d4 ;higher 16 bits
- move.w d4,d3 ;
- divu #10,d3 ;divide higher 16 bits
- swap d3 ;store in high word of d3
- move.w d3,d4 ;safe?
- swap d4 ;
- divu #10,d4 ;divide lower 16 bits
- move.w d4,d3 ;
- exg d3,d4 ;
- rts
-
-
- ;--------------------
-
- LTSHexConvert:
- move.l #8,d4 ;8 characters
-
- LTSHexLoop:
- rol.l #4,d0 ;prepare next nybble
-
- move.l d0,d1 ;spare
- andi.l #$0000000F,d1 ;the nybble
-
- move.l #'0',d3 ;ASCII base (for 0-9)
-
- cmpi.l #9,d1 ;normal or a-f
- ble LTSHexDec
-
- move.l d2,d3 ;new base (A-F or a-f)
- subi.l #$A,d1 ;new value :-)
-
- LTSHexDec:
- add.l d1,d3 ;add soup base, cover it and
- move.b d3,(a0)+ ;wait for 3 minutes :-)
-
- subq.l #1,d4 ;
- bne LTSHexLoop
-
- move.b #0,(a0) ;terminate
- suba.l #1,a0 ;
- movem.l (sp)+,d2-d4 ;give it back..
- move.l #9,d0 ;no way for 8 :-)
- rts
-
- ;--------------------
-
-
- LTSBinConvert:
- move.l #32,d4 ;8 characters
-
- LTSBinLoop:
- rol.l #1,d0 ;one bit
-
- move.l d0,d1 ;spare
- andi.l #$00000001,d1 ;the bit
-
- move.l #'0',d3 ;ASCII base
-
- add.l d1,d3 ;do it again
- move.b d3,(a0)+ ;
-
- subq.l #1,d4 ;
- bne LTSBinLoop
-
- move.b #0,(a0) ;terminate
- suba.l #1,a0 ;
- movem.l (sp)+,d2-d4 ;give it back..
- move.l #33,d0 ;am I sure of that?
- rts
-
-
- **********************************************************************
-
-